using System;
using DG.Tweening;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace BF.UI
{
    [RequireComponent(typeof(Image))]
    /// <summary>
    /// 弹窗
    /// </summary>
    public abstract class Dialog : MonoBehaviour
    {
        private RectTransform _rectTransform;

        public RectTransform rectTransform
        {
            get
            {
                if (_rectTransform == null)
                {
                    _rectTransform = transform as RectTransform;
                }
                return _rectTransform;
            }
        }

        public enum DialogStatus
        {
            None,
            Init,
            Opening,
            Opened,
            Closing,
            Disable,
            Closed
        }
        /// <summary>
        /// 弹窗状态
        /// </summary>
        public DialogStatus dialogStatus { get; private set; }
        /// <summary>
        /// 弹窗关闭时是否删除GameObject
        /// </summary>
        [Tooltip("弹窗关闭时是否删除GameObject")]
        public bool isDestroyOnClose = true;
        /// <summary>
        /// 弹窗打开时是否释放弹窗预制体
        /// </summary>
        [Tooltip("弹窗打开时是否释放弹窗预制体")]
        public bool isUnloadPrefabOnShow = false;
        /// <summary>
        /// 是否播放弹窗打开音效
        /// </summary>
        [Tooltip("是否播放弹窗打开音效")]
        public bool isPlayOpenSound = true;
        /// <summary>
        /// 是否播放弹窗关闭音效
        /// </summary>
        [Tooltip("是否播放弹窗关闭音效")]
        public bool isPlayCloseSound = true;
        /// <summary>
        /// 是否播放弹窗打开动画
        /// </summary>
        [Tooltip("是否播放弹窗打开动画")]
        public bool isPlayOpenAnimation = false;
        /// <summary>
        /// 是否播放弹窗关闭动画
        /// </summary>
        [Tooltip("是否播放弹窗关闭动画")]
        public bool isPlayCloseAnimation = false;

        public Canvas canvas;
        protected RectTransform content;
        protected Image bgImage;

        private event Action<Dialog> _onDialogOpened;
        private event Action<Dialog> _onDialogClose;
        private event Action<Dialog> _onDialogDisable;
        private event Action<Dialog> _onDialogDestroy;

        private event Action _onOpened;
        private event Action _onClose;
        private event Action _onDisable;
        private event Action _onDestroy;


        protected virtual void Awake()
        {
            dialogStatus = DialogStatus.None;

            bgImage = GetComponent<Image>();
            content = transform.Find("Content") as RectTransform;
            if (content == null)
            {
                content = transform.Find("Fit/Content") as RectTransform;
            }

            transform.SetAsLastSibling();

            dialogStatus = DialogStatus.Init;
        }

        protected virtual void OnEnable()
        {
            dialogStatus = DialogStatus.Opening;

            if (isPlayOpenSound)
            {
                PlayOpenSound();
            }

            if (isPlayOpenAnimation && content != null)
            {
                PlayOpenAnimation();
            }
            else
            {
                _onOpened?.Invoke();
                _onDialogOpened?.Invoke(this);

                dialogStatus = DialogStatus.Opened;
            }
        }

        protected virtual void OnDisable()
        {
            dialogStatus = DialogStatus.Disable;

            _onDisable?.Invoke();
            _onDialogDisable?.Invoke(this);

            _onDialogOpened = null;
            _onDialogClose = null;
            _onDialogDisable = null;

            _onOpened = null;
            _onClose = null;
            _onDisable = null;
        }

        protected virtual void OnDestroy()
        {
            dialogStatus = DialogStatus.None;

            _onDestroy?.Invoke();
            _onDialogDestroy?.Invoke(this);
            _onDialogDestroy = null;
            _onDestroy = null;
        }


        public abstract int GetCanvasOrder();

        /// <summary>
        /// 弹窗是否打开
        /// </summary>
        public bool IsDialogShowing()
        {
            return this != null
                && this.gameObject.activeSelf
                && this.dialogStatus != Dialog.DialogStatus.Closing
                && this.dialogStatus != Dialog.DialogStatus.Closed;
        }

        protected virtual void PlayOpenSound()
        {
        }

        protected virtual void PlayCloseSound()
        {
        }

        private void PlayOpenAnimation()
        {
            Tweener anim = GetOpenAnimation();
            if (anim == null)
            {
                _onOpened?.Invoke();
                _onDialogOpened?.Invoke(this);
                dialogStatus = DialogStatus.Opened;
            }
            else
            {
                anim.OnComplete(() => {
                    _onOpened?.Invoke();
                    _onDialogOpened?.Invoke(this);

                    dialogStatus = DialogStatus.Opened;
                });
            }
        }

        protected virtual Tweener GetOpenAnimation()
        {
            return null;
        }

        private void PlayCloseAnimation()
        {
            Tweener anim = GetCloseAnimation();
            if (anim == null)
            {
                DoClose();
            }
            else
            {
                anim.OnComplete(DoClose);
            }
        }

        protected virtual Tweener GetCloseAnimation()
        {
            return null;
        }

        public bool IsOpened()
        {
            if (this == null || gameObject == null)
            {
                return false;
            }

            return dialogStatus <= DialogStatus.Opened && gameObject.activeSelf;
        }

        public void Close()
        {
            if (this == null || gameObject == null)
            {
                return;
            }

            if (dialogStatus > DialogStatus.Opened)
            {
                return;
            }

            dialogStatus = DialogStatus.Closing;

            _onClose?.Invoke();
            _onDialogClose?.Invoke(this);

            if (isPlayCloseSound)
            {
                PlayCloseSound();
            }

            if (isPlayCloseAnimation)
            {
                PlayCloseAnimation();
            }
            else
            {
                DoClose();
            }
        }

        private void DoClose()
        {
            if (isDestroyOnClose)
            {
                UnityEngine.Object.Destroy(gameObject);
            }
            else
            {
                gameObject.SetActive(false);
            }

            dialogStatus = DialogStatus.Closed;
        }

        public Dialog SetOnOpen(Action action)
        {
            _onOpened += action;

            return this;
        }

        public Dialog SetOnOpend(Action<Dialog> action)
        {
            _onDialogOpened += action;

            return this;
        }

        public Dialog SetOnClose(Action action)
        {
            _onClose += action;

            return this;
        }

        public Dialog SetOnClose(Action<Dialog> action)
        {
            _onDialogClose += action;

            return this;
        }

        public Dialog SetOnDisable(Action action)
        {
            _onDisable += action;

            return this;
        }

        public Dialog SetOnDisable(Action<Dialog> action)
        {
            _onDialogDisable += action;

            return this;
        }

        public Dialog SetOnDestroy(Action action)
        {
            _onDestroy += action;

            return this;
        }

        public Dialog SetOnDestroy(Action<Dialog> action)
        {
            _onDialogDestroy += action;

            return this;
        }
    }
}
